/*
 * Test_Graph.cpp
 *
 *  Created on: Apr 1, 2014
 *      Author: zby
 */
#include "Test_Graph.h"

using namespace graph;

CppUnit::Test* Test_Graph::suite(){
    CppUnit::TestSuite* suiteOfTests = new CppUnit::TestSuite("Test_Graph");
    suiteOfTests->addTest(new CppUnit::TestCaller<Test_Graph>("test_def_constructor",&Test_Graph::test_def_constructor));
    suiteOfTests->addTest(new CppUnit::TestCaller<Test_Graph>("test_def_constructor",&Test_Graph::test_def_constructor_cpy));
    suiteOfTests->addTest(new CppUnit::TestCaller<Test_Graph>("test_AddEdge",&Test_Graph::test_AddEdge));
    suiteOfTests->addTest(new CppUnit::TestCaller<Test_Graph>("test_DeleteEdge",&Test_Graph::test_DeleteEdge));
    suiteOfTests->addTest(new CppUnit::TestCaller<Test_Graph>("test_Adjacent",&Test_Graph::test_Adjacent));
    suiteOfTests->addTest(new CppUnit::TestCaller<Test_Graph>("test_Neighbors",&Test_Graph::test_Neighbors));
    suiteOfTests->addTest(new CppUnit::TestCaller<Test_Graph>("test_Get_node_value",&Test_Graph::test_Get_node_value));
    suiteOfTests->addTest(new CppUnit::TestCaller<Test_Graph>("test_Set_node_value",&Test_Graph::test_Set_node_value));
    suiteOfTests->addTest(new CppUnit::TestCaller<Test_Graph>("test_Get_edge_value",&Test_Graph::test_Get_edge_value));
    suiteOfTests->addTest(new CppUnit::TestCaller<Test_Graph>("test_Set_edge_value",&Test_Graph::test_Set_edge_value));
    suiteOfTests->addTest(new CppUnit::TestCaller<Test_Graph>("test_friend_op",&Test_Graph::test_friend_op));

    return suiteOfTests;
}

void Test_Graph::test_def_constructor(void){
    //check connection on diagonal
    CPPUNIT_ASSERT(true==g1->Adjacent(0,0) && true==g1->Adjacent(1,1) && true==g1->Adjacent(2,2) && true==g1->Adjacent(3,3));
    //check connection outside of diagonal
    CPPUNIT_ASSERT(false==g1->Adjacent(0,1) && false==g1->Adjacent(1,0) && false==g1->Adjacent(3,2) && false==g1->Adjacent(2,3) &&
            false==g1->Adjacent(3,0) && false==g1->Adjacent(0,3));
}

void Test_Graph::test_def_constructor_cpy(void){
    Graph *gx,*gy;
    gx=NULL;
    gy=NULL;

    gx=new Graph(16);
    gx->AddEdge(0,2,2);     gx->Set_node_value(0,31);
    gx->AddEdge(0,15,15);     gx->Set_node_value(15,32);
    gx->AddEdge(10,13,25);     gx->Set_node_value(10,33);
    gx->AddEdge(8,7,15);     gx->Set_node_value(8,34);
    gy=new Graph(*gx);

    CPPUNIT_ASSERT(true==gy->Adjacent(2,0) && true==gy->Adjacent(15,0) &&
                   true==gy->Adjacent(13,10) && true==gy->Adjacent(7,8) &&
                   false==gy->Adjacent(4,6) && false==gy->Adjacent(9,8) &&
                   2==gy->Get_edge_value(2,0) &&  15==gy->Get_edge_value(15,0) &&
                   25==gy->Get_edge_value(13,10) &&  15==gy->Get_edge_value(7,8) &&
                   31==gy->Get_node_value(0) && 32==gy->Get_node_value(15) &&
                   33==gy->Get_node_value(10) && 34==gy->Get_node_value(8));

    if(gx!=NULL) delete gx;
    if(gx!=NULL) delete gy;
    gx=NULL;
    gy=NULL;
}

void Test_Graph::test_AddEdge(void){
    //adding existing edge shall be forbidden
    CPPUNIT_ASSERT(false==g1->AddEdge(0,0,5) && false==g1->AddEdge(3,3,10));
    //if edge doesn't exist adding shall be allowed
    CPPUNIT_ASSERT(true==g1->AddEdge(0,3,15) && false==g1->AddEdge(3,0,15) &&
                   true==g1->AddEdge(0,1,3) && false==g1->AddEdge(1,0,3));
}

void Test_Graph::test_DeleteEdge(void){
    //you can't delete diagonal
    CPPUNIT_ASSERT(false==g1->DeleteEdge(0,0) && false==g1->DeleteEdge(3,3) );
    g1->AddEdge(1,2,20);
    g1->AddEdge(3,2,30);
    unsigned int x=g1->E();
    //must be possible delete existing edges
    CPPUNIT_ASSERT(x==2);
    CPPUNIT_ASSERT( true==g1->DeleteEdge(1,2) && false==g1->DeleteEdge(1,2) && false==g1->DeleteEdge(2,1) &&
                    true==g1->DeleteEdge(3,2) && false==g1->DeleteEdge(3,2) && false==g1->DeleteEdge(2,3)    );
    x=g1->E();
    CPPUNIT_ASSERT(x==0);
}

void Test_Graph::test_Adjacent(void){
    //add some edges
    g1->AddEdge(1,3,20);
    g1->AddEdge(3,2,30);
    //check if added
    CPPUNIT_ASSERT(true==g1->Adjacent(1,3) && true==g1->Adjacent(3,1) &&
                   true==g1->Adjacent(3,2) && true==g1->Adjacent(2,3) &&
                   false==g1->Adjacent(0,1) && false==g1->Adjacent(0,2) &&
                   false==g1->Adjacent(0,3) && false==g1->Adjacent(1,2) );
    //delete edges
    g1->DeleteEdge(1,3);
    g1->DeleteEdge(3,2);
    //check if deleted
    CPPUNIT_ASSERT( false==g1->Adjacent(1,3) && false==g1->Adjacent(3,1) &&
                    false==g1->Adjacent(3,2) && false==g1->Adjacent(2,3) &&
                    false==g1->Adjacent(0,1) && false==g1->Adjacent(0,2) &&
                    false==g1->Adjacent(0,3) && false==g1->Adjacent(1,2) );
}

void Test_Graph::test_Neighbors(void){
    //at the beginning there is no neighbors
    std::vector<Node> vtest=g1->Neighbors(0);
    CPPUNIT_ASSERT(0==vtest.size());
    //adding some edges
    g1->AddEdge(0,2,20);
    g1->AddEdge(0,3,30);
    vtest=g1->Neighbors(0);
    CPPUNIT_ASSERT(2==vtest.size() && 2==vtest[0] && 3==vtest[1]);
    //adding some edges
    g1->AddEdge(3,0,20);
    g1->AddEdge(3,3,30); // false
    vtest=g1->Neighbors(3);
    CPPUNIT_ASSERT(1==vtest.size() && 0==vtest[0] );
    //-----------------
    g2->AddEdge(0,1,10);
    g2->AddEdge(0,7,10);
    vtest=g2->Neighbors(0);
    CPPUNIT_ASSERT(2==vtest.size() && 1==vtest[0] && 7==vtest[1]);
}

void Test_Graph::test_Get_node_value(void){
    //at the beginning
    CPPUNIT_ASSERT(Graph::NodeValueInit==g1->Get_node_value(0) && Graph::NodeValueInit==g1->Get_node_value(1) &&
                   Graph::NodeValueInit==g1->Get_node_value(2) && Graph::NodeValueInit==g1->Get_node_value(3)  );
    //set nodes values
    g1->Set_node_value(0,0);
    g1->Set_node_value(1,1);
    g1->Set_node_value(2,2);
    g1->Set_node_value(3,3);
    CPPUNIT_ASSERT(0==g1->Get_node_value(0) && 1==g1->Get_node_value(1) &&
                   2==g1->Get_node_value(2) && 3==g1->Get_node_value(3)  );
    //set new value
    g1->Set_node_value(0,5);
    CPPUNIT_ASSERT(5==g1->Get_node_value(0) && 1==g1->Get_node_value(1) &&
                   2==g1->Get_node_value(2) && 3==g1->Get_node_value(3)  );
}

void Test_Graph::test_Set_node_value(void){
    //at the beginning
    CPPUNIT_ASSERT(Graph::NodeValueInit==g1->Get_node_value(0) && Graph::NodeValueInit==g1->Get_node_value(1) &&
                   Graph::NodeValueInit==g1->Get_node_value(2) && Graph::NodeValueInit==g1->Get_node_value(3)  );
    //set nodes values
    g1->Set_node_value(0,0);
    g1->Set_node_value(1,1);
    g1->Set_node_value(2,2);
    g1->Set_node_value(3,3);
    CPPUNIT_ASSERT(0==g1->Get_node_value(0) && 1==g1->Get_node_value(1) &&
                   2==g1->Get_node_value(2) && 3==g1->Get_node_value(3)  );
    //set new value
    g1->Set_node_value(0,5);
    CPPUNIT_ASSERT(5==g1->Get_node_value(0) && 1==g1->Get_node_value(1) &&
                   2==g1->Get_node_value(2) && 3==g1->Get_node_value(3)  );
}

void Test_Graph::test_Get_edge_value(void){
    //at the beginning
    CPPUNIT_ASSERT( 0==g1->Get_edge_value(0,0) && Graph::EdgeInit==g1->Get_edge_value(0,1) && Graph::EdgeInit==g1->Get_edge_value(0,2) &&
                    Graph::EdgeInit==g1->Get_edge_value(0,3) && 0==g1->Get_edge_value(3,3));
    g1->Set_edge_value(0,3,5);
    CPPUNIT_ASSERT(5==g1->Get_edge_value(0,3) && 5==g1->Get_edge_value(3,0));
}

void Test_Graph::test_Set_edge_value(void){
    //at the beginning
    CPPUNIT_ASSERT( 0==g1->Get_edge_value(0,0) && Graph::EdgeInit==g1->Get_edge_value(0,1) && Graph::EdgeInit==g1->Get_edge_value(0,2) &&
                    Graph::EdgeInit==g1->Get_edge_value(0,3) && 0==g1->Get_edge_value(3,3));
    g1->Set_edge_value(0,3,5);
    CPPUNIT_ASSERT(5==g1->Get_edge_value(0,3) && 5==g1->Get_edge_value(3,0));
}

void Test_Graph::test_friend_op(void){
    //at the beginning - no connections
    using namespace std;
    cout<<endl<<"Graph no connection:"<<endl;
    cout<<*g1<<endl;
    //add connections to make 'round' graph
    g1->AddEdge(0,1,30);
    g1->AddEdge(1,2,31);
    g1->AddEdge(2,3,32);
    g1->AddEdge(3,0,33);
    cout<<"Graph 'round' connections:"<<endl;
    cout<<*g1<<endl;
}

